package org.jeecg.api.controller.user;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.jeecg.api.annotation.ApiNeedLogin;
import org.jeecg.api.dto.req.user.AuthDto;
import org.jeecg.api.dto.resp.user.UserInfoDto;
import org.jeecg.api.dto.req.user.WxMiniappLoginDto;
import org.jeecg.api.utils.MiniappSpringContextUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.util.JwtTokenUtil;
import org.jeecg.common.system.util.SignDO;
import org.jeecg.common.util.BeanUtils;
import org.jeecg.common.util.qiniu.QiNiuUploadUtil;
import org.jeecg.modules.recruit.appuser.entity.MmAppUser;
import org.jeecg.modules.recruit.appuser.service.IMmAppUserAuthService;
import org.jeecg.modules.recruit.appuser.service.IMmAppUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 微信小程序用户接口
 */
@RestController
@RequestMapping("/app/user/")
@Api(tags = "用户信息相关接口")
@Slf4j
public class WxMiniappUserController {

    @Autowired
    private WxMaService wxService;

    @Autowired
    private IMmAppUserService mmAppUserService;

    @Autowired
    private IMmAppUserAuthService mmAppUserAuthService;

    private final static ExecutorService executorService = Executors.newFixedThreadPool(3,
            new BasicThreadFactory.Builder().namingPattern("user_info-%d").daemon(true).build());

    /**
     * 登陆接口
     */
    @PostMapping(value = "/login")
    @ApiOperation(value = "小程序登录")
    public Result<UserInfoDto> login(@Valid @RequestBody WxMiniappLoginDto queryDto) {
        if (StringUtils.isBlank(queryDto.getCode())) {
            return Result.error("参数错误");
        }

        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(queryDto.getCode());
            // 解密用户信息
            MmAppUser examUserDO = new MmAppUser();
            if (queryDto.getEncryptedData() != null && queryDto.getIv() != null) {
                WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(session.getSessionKey(), queryDto.getEncryptedData(), queryDto.getIv());
                examUserDO.setNick(userInfo.getNickName());
                examUserDO.setFace(userInfo.getAvatarUrl());
            }

            examUserDO.setOpenid(session.getOpenid());
            MmAppUser user = mmAppUserService.register(examUserDO, queryDto.getPopularizeId());
            UserInfoDto userInfoDto = BeanUtils.copyProperties(user, UserInfoDto.class);
            userInfoDto.setToken(JwtTokenUtil.sign(user.getId(), session.getOpenid(), session.getSessionKey()));
            return Result.OK(userInfoDto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("登录失败！");
        }
    }

    /**
     * <pre>
     * 获取用户绑定手机号信息
     * </pre>
     */
    @GetMapping("/phone")
    @ApiNeedLogin
    @ApiOperation(value = "获取用户手机号码")
    public Result<WxMaPhoneNumberInfo> phone(@ModelAttribute WxMiniappLoginDto queryDto) {
        SignDO signDO = MiniappSpringContextUtils.getSignDO();
        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(signDO.getSessionKey(), queryDto.getEncryptedData(), queryDto.getIv());
        MmAppUser user = new MmAppUser();
        user.setId(signDO.getUserId());
        user.setPhoneNo(phoneNoInfo.getPhoneNumber());
        mmAppUserService.updateById(user);
        CompletableFuture.runAsync(() -> {
            try {
                //上传 更新用户二维码地址
                String scene = String.format("code=", phoneNoInfo.getPhoneNumber());
                byte[] paths = wxService.getQrcodeService().createWxaCodeUnlimitBytes(scene, "path", 430, true, null, false);
                String fileName = "popularize_" + phoneNoInfo.getPhoneNumber() + ".jpg";
                QiNiuUploadUtil.upLoad(paths, fileName);
//               todo  user.setPopularizeUrl("");
                mmAppUserService.updateById(user);
            } catch (Exception e) {
                log.error(String.format("创建推广二维码失败！userId:%s,phone:%s", signDO.getUserId(), phoneNoInfo.getPhoneNumber()), e);
            }
        }, executorService);
        return Result.OK(phoneNoInfo);
    }

    @GetMapping("info")
    @ApiNeedLogin
    @ApiOperation(value = "获取用户信息")
    public Result<UserInfoDto> getUserInfo(HttpServletRequest request) {
        SignDO signDO = MiniappSpringContextUtils.getSignDO();
        MmAppUser mmAppUser = mmAppUserService.getById(signDO.getUserId());
        UserInfoDto userInfoDto = BeanUtils.copyProperties(mmAppUser, UserInfoDto.class);
        userInfoDto.setPhone(mmAppUser.getPhoneNo());
        userInfoDto.setToken(JwtTokenUtil.sign(signDO.getUserId(), mmAppUser.getOpenid(), signDO.getSessionKey()));
        return Result.OK(userInfoDto);
    }

    @PostMapping("auth")
    @ApiOperation(value = "实名认证")
    @ApiNeedLogin
    public Result<UserInfoDto> auth(@RequestBody AuthDto authDto) {
        SignDO signDO = MiniappSpringContextUtils.getSignDO();
        authDto.setUserId(signDO.getUserId());
        mmAppUserAuthService.auth(authDto);
        return Result.OK();
    }


    @GetMapping("prizeDraw")
    @ApiOperation(value = "抽奖")
    @ApiNeedLogin
    public Result<UserInfoDto> prizeDraw() {
        //todo
        return Result.OK();
    }

    public static void main(String[] args) {
        String scene = String.format("code=%s", "13122202002");
        System.out.println(scene);
    }

}